// app/extend/context.js
const crypto=require('crypto')
module.exports = {
  // 成功提示
  apiSuccess(data = '', msg = 'ok', code = 200) {
    this.body = {
      msg,
      data
    };
    this.status = code;
  },
  // 失败提示
  apiFail(data = '', msg = 'fail', code = 400) {
    this.body = {
      msg,
      data
    };
    this.status = code;
  },
  // 页面失败提示
  async pageFail(data = '', code = 404) {
    return await this.render('admin/common/404.html', {
      data,
      code
    })
  },
  // 生成token
  getToken(value) {
    return this.app.jwt.sign(value, this.app.config.jwt.secret);
  },
  // 验证token
  checkToken(token) {
    return this.app.jwt.verify(token, this.app.config.jwt.secret)
  },
  // 验证密码
  async checkPassword(password, hash_password) {
    // 先对需要验证的密码进行加密
    const hmac = crypto.createHash("sha256", this.app.config.crypto.secret);
    hmac.update(password);
    password = hmac.digest("hex");
    let res = password === hash_password;
    if (!res) {
      this.throw(400, '密码错误');
    }
    return true;
  },
  // 生成随机字符串
  randomString(length) {
    const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var result = '';
    for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
    return result;
  },
  // 分页
  async page(model, where, options = {}) {
    let page = this.query.page ? parseInt(this.query.page) : 1;
    let limit = this.query.limit ? parseInt(this.query.limit) : 10;
    let offset = (page - 1) * limit;
    if (!options.order) {
      options.order = [
        ['id', 'DESC']
      ]
    }
    let res = await this.app.model[model].findAndCountAll({
      where,
      offset,
      limit,
      ...options
    })

    // 计算总页数
    let totalPage = Math.ceil(res.count / limit)
    // 定义 单个页面
    let pageEl = ''
    // 处理参数的问题 url 转为以&拼接的方式
    // 先把page 和limit去掉
    // 其他参数
    let query = {
      ...this.query
    }
    if (query.hasOwnProperty('page')) {
      delete query.page
    }
    if (query.hasOwnProperty('limit')) {
      delete query.limit
    }
    // 对象转&拼接字符串
    const urlEncode = (param, key, encode) => {
      if (param == null) return '';
      var paramStr = '';
      var t = typeof (param);
      if (t == 'string' || t == 'number' || t == 'boolean') {
        paramStr += '&' + key + '=' + ((encode == null || encode) ? encodeURIComponent(param) : param);
      } else {
        for (var i in param) {
          var k = key == null ? i : key + (param instanceof Array ? '[' + i + ']' : '.' + i)
          paramStr += urlEncode(param[i], k, encode)
        }
      }
      return paramStr;
    }

    query = urlEncode(query)

    // 循环页面 添加active
    for (let index = 1; index <= totalPage; index++) {
      let active = ''
      if (index === page) {
        active = 'active'
        console.log('active')
      }
      pageEl += `<li class="page-item ${active}"><a class="page-link" href="?page=${index}&limit=${limit}${query}">${index}</a></li>`
    }
    // 判断 是是否显示 上一页和显示下一页
    const preDisabled = page <= 1 ? 'disabled' : ''
    const nextDisabled = page > totalPage ? 'disabled' : ''
    // 构建分页页码
    let pageRender = `
        <ul class="pagination">
									<li class="page-item">
										<a class="page-link ${preDisabled}" href="?page=${page-1}&limit=${limit}${query}" aria-label="Previous">
											<span aria-hidden="true">«</span>
											<span class="sr-only">Previous</span>
										</a>
									</li>
								${pageEl}
									<li class="page-item">
										<a class="page-link ${nextDisabled}" href="?page=${page+1}&limit=${limit}${query}" aria-label="Next">
											<span aria-hidden="true">»</span>
											<span class="sr-only">Next</span>
										</a>
									</li>
								</ul>
        `
    // 将分页挂载到local
    this.locals.pageRender = pageRender
    // 返回数据
    return res.rows
  },
  // 渲染公共模板
  async renderTemplate(params = {}) {
    // 获得cookie的消息提示（闪存）
    let toast = this.cookies.get('toast', {
      encrypt: true
    })
    params.toast = toast ? JSON.parse(toast) : null
    // 合并到参数中
    await this.render('/admin/common/template.html', params)
  },
  /* 
  全局消息提示
  1.使用后端的cookie 存入需要提示的数据ok
  2.前端引用vue
  3.前端封装全局vue的自定义组件
  4.后端通过cookie传递数据到前端渲染
  5.前端判断并渲染
  */
  // 全局toast提示
  toast(msg, type = 'danger') {
    this.cookies.set('toast', JSON.stringify({
      msg,
      type
    }), {
      maxAge: 1500,
      encrypt: true
    })
  }
};